/*
 * Sensor.cpp
 *
 *  Created on: Jan 18, 2009
 *      Author: Andrzej Olchawa
 *      mailto: andrzejolchawa@gmail.com
 *      http://www.hardtechnology.org
 *      This is a part of the Armazd project, which is covered by
 *      GNU GPL v2 license.
 */

#include "Sensor.h"
#include "HTFramework/HTThread.cpp"

Sensor::Sensor() {}

Sensor::Sensor(string name, string path, int delay)
{
	executionDelay = delay;

	sensorName = name;
	externalSensorPath = path;

	try
	{
		loadExternalSensor();
	}
	catch (AgentException &e)
	{
		e.printException();
	}
	start();
}

Sensor::~Sensor()
{
	if (externalSensor)
	{
	    destroyExternalSensor(externalSensor);
	}
	if (hExternalModule)
	{
		dlclose(hExternalModule);
	}
}

string Sensor::getSensorName()
{
	return sensorName;
}

string Sensor::getExternalSensorPath()
{
	return externalSensorPath;
}

ExternalSensor *Sensor::getExternalSensor()
{
	return externalSensor;
}

void Sensor::setSensorName(string name)
{
	sensorName = name;
}

void Sensor::setExternalSensorPath(string path)
{
	externalSensorPath = path;
}

void Sensor::loadExternalSensor(string path)
{
	externalSensorPath = path;
	loadExternalSensor();
}

void Sensor::loadExternalSensor()
{
	if (externalSensorPath.empty() || sensorName.empty())
	{
		throw AgentException("Sensor.loadExternalSensor(): externalSensorPath \
							  or sensorName are empty");
	}

	hExternalModule = dlopen(externalSensorPath.c_str(), RTLD_LAZY);
	if(hExternalModule == NULL)
	{
		throw AgentException("Sensor.loadExternalSensor(): " + string(dlerror()));
	}

	createExternalSensor = (externalCreate*) dlsym(hExternalModule, "create");
	const char* dlsym_error = dlerror();
	if (dlsym_error)
	{
		throw AgentException("Sensor.loadExternalSensor(): \
							  Cannot load symbol create: "
							+ string(dlsym_error));
	}

	destroyExternalSensor = (externalDestroy*) dlsym(hExternalModule, "destroy");
	dlsym_error = dlerror();
	if (dlsym_error)
	{
		throw AgentException("Sensor.loadExternalSensor(): \
							  Cannot load symbol destroy: "
							+ string(dlsym_error));
	}

	externalSensor = createExternalSensor();
	if (typeid(externalSensor) != typeid(ExternalSensor*))
	{
		throw AgentException("Sensor.loadExternalSensor(): \
							  incompatible object type with \"ExternalSensor\"");
	}
}

string Sensor::checkParameters()
{
	if (externalSensor)
	{
		string message = "<empty>";

		SensorMessage *msg = externalSensor->getSensorMessage();
		char *rawMsg = externalSensor->getRawMessage();

		if (msg)
		{
			message = msg->getMessage();
		}
		else if (rawMsg)
		{
			message = string(rawMsg);
		}
		return message;
	}
	return NULL;
}

void Sensor::sendDataFromSensors()
{
	if (sender)
	{
		try
		{
			sender->sendData(checkParameters());
		}
		catch (AgentException &e)
		{
			e.printException();
		}
	}
}

void Sensor::run()
{
	while (true)
	{
		if (!interrupt)
		{
			sendDataFromSensors();
			sleep(executionDelay);
		}
	}
}
